package com.adcc.loadsheet.billing.controller;

import com.adcc.aoc.devLib.common.log.Log;
import com.adcc.loadsheet.billing.entity.ScAirlinesEntity;
import com.adcc.loadsheet.billing.entity.ScAirportEntity;
import com.adcc.loadsheet.billing.entity.contractuser.ContractUserAirlinesEntity;
import com.adcc.loadsheet.billing.entity.contractuser.ContractUserEntity;
import com.adcc.loadsheet.billing.exception.ParamValidException;
import com.adcc.loadsheet.billing.exception.PermissionVerifyException;
import com.adcc.loadsheet.billing.service.*;
import com.adcc.loadsheet.billing.util.LogUtil;
import com.adcc.loadsheet.billing.validator.ContractUserEntityVOValidator;
import com.adcc.loadsheet.billing.vo.*;
import com.adcc.loadsheet.billing.vo.chargerule.BillingRuleEntityVO;
import com.adcc.loadsheet.billing.vo.contractuser.ContractUserEntityVO;
import com.adcc.loadsheet.billing.vo.contractuser.ContractUserTreeVO;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * 合同用户管理Controller层
 * Created by zhaoml on 2020/4/13.
 */
@Controller
@RequestMapping(value = "contractuser")
@Api(value = "/contractuser", description = "合同用户相关操作controller")
public class ContractUserController extends BasisController{
    @Autowired
    ContractUserService contractUserService;

    @Autowired
    ContractUserAirportService contractUserAirportService;

    @Autowired
    AirportService airportService;

    @Autowired
    ContractUserAirlinesService contractUserAirlinesService;

    @Autowired
    AirlinesService airlinesService;

    @Autowired
    ContractUserEntityVOValidator contractUserEntityVOValidator;
    @InitBinder("contractUserEntityVO")
    public void initBainder(WebDataBinder binder) {
        binder.replaceValidators(this.contractUserEntityVOValidator);
    }

    /**
     * 进入合同用户管理页面
     *
     * @param model
     * @return
     */
    @PreAuthorize("hasPermission('','ContractUserManage')")
    @GetMapping(value = "tocontractusermanage")
    @ApiOperation(value = "/tocontractusermanage", notes = "跳转到合同用户管理页面", httpMethod = "GET")
    public String toContractUserManage(Model model) {
        return "contractUser/contractuser-manage";
    }

    /**
     * 合同用户Tree
     *
     * @return
     */
    @RequestMapping(value = "/getContractUserTree", method = RequestMethod.GET)
    public @ResponseBody
    List<ContractUserTreeVO> getContractUserTree() {
        List<ContractUserTreeVO> list = Lists.newArrayList();
        try {
            //获取合同用户Tree
            list = contractUserService.getTreeNode();
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "获取合同用户Tree出错", ex);
        }
        return list;
    }

    /**
     * 页面查询合同用户
     *
     * @param map
     * @return
     */
    @PostMapping(value = "findContractUser", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/findContractUser", notes = "查询合同用户", httpMethod = "POST")
    @ResponseBody
    public ResultVO findContractUser(@RequestBody Map<String, Object> map) {
        ResultVO vo = new ResultVO();
        try {
            Map<String, Object> paramMap = inputContractUserParams(map);
            ContractUserEntityVO contractUserEntityVO = contractUserService.findByContractUserId(paramMap);
            vo.getData().put("contractUserEntityVO", contractUserEntityVO);
        } catch (PermissionVerifyException pe) {
            vo.setStatus(ResultStatus.FAILED);
            vo.getData().put("msg", pe.getMessage());
        } catch (ParamValidException pe) {
            vo.setStatus(ResultStatus.FAILED);
            vo.getData().put("msg", pe.getMessage());
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "查询合同用户出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason(String.format(ResultVO.ER_CALL_EX_FAILED, "Query findContractUser", ex.fillInStackTrace()));
        }
        return vo;
    }

    /**
     * 编辑合同用户
     *
     * @param contractUserEntityVO
     * @param br
     * @return
     * @throws Exception
     */
    @PostMapping(value = "editContractUser", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/editContractUser", notes = "编辑合同用户", httpMethod = "POST")
    @ResponseBody
    public ResultVO editContractUser(@Valid @RequestBody ContractUserEntityVO contractUserEntityVO,
                                    BindingResult br) throws Exception {
        ResultVO vo = new ResultVO();
        try {
            if (br.hasErrors()) {
                vo.setStatus(ResultStatus.FAILED);
                vo.setErrorReason(br.getAllErrors().get(0).getCode());
                return vo;
            }
            ContractUserEntity contractUserEntity = contractUserService.edit(contractUserEntityVO);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("msg", "编辑成功！");
            vo.getData().put("contractUserId", contractUserEntity.getContractUserId());
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "编辑合同用户出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("编辑合同用户出错");
            LogUtil.errorLog(ContractUserController.class, ex, "editContractUser()");
        }
        return vo;
    }

    /**
     * 删除合同用户
     *
     * @param contractUserId
     * @return
     */
    @GetMapping(value = "deleteContractUser")
    @ApiOperation(value = "/deleteContractUser", notes = "删除合同用户", httpMethod = "GET")
    @ResponseBody
    public ResultVO deleteContractUser(Integer contractUserId) {
        ResultVO vo = new ResultVO();
        String res = "";
        try {
            ContractUserEntity contractUserEntity = contractUserService.selectByPrimaryKey(contractUserId);
            if (contractUserEntity == null) {
                vo.setStatus(ResultStatus.FAILED);
                vo.setErrorReason("合同用户不存在！");
                return vo;
            }
            res = contractUserService.deleteByContractUserId(contractUserId);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("msg", res);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "删除合同用户出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("删除合同用户出错");
            LogUtil.errorLog(ContractUserController.class, ex, "deleteContractUser()");
        }
        return vo;
    }

    /**
     * 查询机场，并设置是否选中
     *
     * @param contractUserEntityVO
     * @return
     */
    @PostMapping(value = "findAirports", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/findAirports", notes = "查询机场", httpMethod = "POST")
    @ResponseBody
    public ResultVO findAirports(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            Integer contractUserId = contractUserEntityVO.getContractUserId();
            Map<String, Object> map = Maps.newHashMap();
            List<ScAirportEntityVO> airportEntityVOList = contractUserService.selectAirports(contractUserId,map);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("airportEntityVOList", airportEntityVOList);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "查询机场出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("查询机场出错");
        }
        return vo;
    }

    /**
     * 查询航司，并设置是否选中
     *
     * @param contractUserEntityVO
     * @return
     */
    @PostMapping(value = "findAirLines", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/findAirLines", notes = "查询航司", httpMethod = "POST")
    @ResponseBody
    public ResultVO findAirLines(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            Integer contractUserId = contractUserEntityVO.getContractUserId();
            Map<String, Object> map = Maps.newHashMap();
            List<ScAirlinesEntityVO> airlinesEntityVOList = contractUserService.selectAirlines(contractUserId,map);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("airlinesEntityVOList", airlinesEntityVOList);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "查询航司出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("查询航司出错");
        }
        return vo;
    }

    /**
     * 编辑计费范围
     * @param contractUserEntityVO 包含contractUserId和airportIds
     * @return
     */
    @PostMapping(value = "editBillingRange", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/editBillingRange", notes = "编辑计费范围", httpMethod = "POST")
    @ResponseBody
    public ResultVO editBillingRange(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            //当前合同用户主键ID
            Integer contractUserId = contractUserEntityVO.getContractUserId();
            if (contractUserId != null) {
                ContractUserEntity entity = contractUserService.selectByPrimaryKey(contractUserId);
                if (entity == null) {
                    vo.setStatus(ResultStatus.FAILED);
                    vo.setErrorReason("合同用户不存在！");
                    return vo;
                }
            }

            String res = "";
            //用户在合同用户管理页面中选择一条记录，点击“计费范围”，
            //弹出“计费范围”选择界面，可以选择当前合同用户计费的机场和航司（机场与航司为与的关系），
            //如果选择的计费机场和航司已经被其他合同用户选择过，则系统进行提示“**机场/**航司已经被**合同用户关联，不能保存！”
            for(String airportId : contractUserEntityVO.getAirportIds().split(",")){
                //查询与机场绑定的其他合同用户
                List<Integer> contractUserIdList_airport = contractUserAirportService.selectOtherContractUserIds(Integer.valueOf(airportId),contractUserId);
                //循环与机场绑定的其他合同用户
                for(int i = 0;i < contractUserIdList_airport.size();i ++){
                    Integer contractUserId_airport = contractUserIdList_airport.get(i);
                    //再判断航司
                    for(String airlineId : contractUserEntityVO.getAirlineIds().split(",")) {
                        //查询与航司和contractUserId_airport绑定的数据
                        List<ContractUserAirlinesEntity> contractUserIdList_airline = contractUserAirlinesService.selectContractUserIds(Integer.valueOf(airlineId),contractUserId_airport);
                        if(contractUserIdList_airline != null && contractUserIdList_airline.size() > 0){ //不为空，说明有其他合同用户同时关联了机场和航司
                            ScAirportEntity airportEntity = airportService.selectByPrimaryKey(Integer.valueOf(airportId));  //机场
                            ScAirlinesEntity airlinesEntity = airlinesService.selectByPrimaryKey(Integer.valueOf(airlineId));   //航司
                            ContractUserEntity contractUserEntity = contractUserService.selectByPrimaryKey(contractUserId_airport); //合同用户
                            res = airportEntity.getAirportShortname() + "机场/" + airlinesEntity.getChsShortname() + "航司已经被" + contractUserEntity.getUserAbbrev() + "合同用户关联，不能保存！";
                            vo.setStatus(ResultStatus.FAILED);
                            vo.setErrorReason(res);
                            return vo;
                        }
                    }
                }
            }

            //编辑计费范围(包含contractUserId、airportIds、airlineIds)
            res = contractUserService.editBillingRange(contractUserEntityVO);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("msg", res);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "编辑计费范围失败", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("编辑计费范围失败！");
            LogUtil.errorLog(ContractUserController.class, ex, "editBillingRange()");
        }
        return vo;
    }

    //获取关联用户Tree，并设置是否选中
    @PostMapping(value = "getAssociatedUsersTree", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/getAssociatedUsersTree", notes = "获取关联用户Tree", httpMethod = "POST")
    public @ResponseBody
    List<PbStaffTreeVO> getAssociatedUsersTree(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        List<PbStaffTreeVO> list = Lists.newArrayList();
        try {
            Integer contractUserId = contractUserEntityVO.getContractUserId();
            Map<String, Object> map = Maps.newHashMap();
            if(!userContext.getCurrentUser().isSuperAdmin()){
                map.put("contractUserId",contractUserId);
            }
            list = contractUserService.getAssociatedUsersTreeNode(contractUserId,map);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "获取关联用户Tree出错", ex);
        }
        return list;
    }

    //编辑关联用户
    @PostMapping(value = "editAssociatedUsers", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/editAssociatedUsers", notes = "编辑关联用户", httpMethod = "POST")
    @ResponseBody
    public ResultVO editAssociatedUsers(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            if (contractUserEntityVO.getContractUserId() != null) {
                ContractUserEntity entity = contractUserService.selectByPrimaryKey(contractUserEntityVO.getContractUserId());
                if (entity == null) {
                    vo.setStatus(ResultStatus.FAILED);
                    vo.setErrorReason("合同用户不存在！");
                    return vo;
                }
            }

            //一个登录用户不能被两个合同用户关联（如果选择的登陆用户已经被其他合同用户关联过，则系统进行提示“用户已经被合同用户关联，不能保存！”）
            String associatedUserRes = contractUserService.selectOtherContractUser(contractUserEntityVO);
            if(!Strings.isNullOrEmpty(associatedUserRes)){
                vo.setStatus(ResultStatus.FAILED);
                vo.setErrorReason(associatedUserRes);
                return vo;
            }

            //编辑关联用户(包含contractUserId、associatedUserIds)
            contractUserService.editAssociatedUsers(contractUserEntityVO);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("msg", "编辑关联用户成功！");
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "编辑关联用户出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("编辑关联用户失败！");
            LogUtil.errorLog(ContractUserController.class, ex, "editAssociatedUsers()");
        }
        return vo;
    }

    //查询计费规则，并设置是否选中
    @PostMapping(value = "findBillingRules", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/findBillingRules", notes = "查询计费规则", httpMethod = "POST")
    @ResponseBody
    public ResultVO findBillingRules(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            Integer contractUserId = contractUserEntityVO.getContractUserId();
            Map<String, Object> map = Maps.newHashMap();
            if(!userContext.getCurrentUser().isSuperAdmin()){
                map.put("PB_LOGIN_ID",userContext.getCurrentUser().getUsername());
            }
            List<BillingRuleEntityVO> billingRuleEntityVOList = contractUserService.selectBillingRules(contractUserId,map);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("billingRuleEntityVOList", billingRuleEntityVOList);
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "查询计费规则出错", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("查询计费规则出错");
        }
        return vo;
    }

    //编辑计费规则
    @PostMapping(value = "editBillingRule", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    @ApiOperation(value = "/editBillingRule", notes = "编辑计费规则", httpMethod = "POST")
    @ResponseBody
    public ResultVO editBillingRule(@RequestBody ContractUserEntityVO contractUserEntityVO) {
        ResultVO vo = new ResultVO();
        try {
            if (contractUserEntityVO.getContractUserId() != null) {
                ContractUserEntity entity = contractUserService.selectByPrimaryKey(contractUserEntityVO.getContractUserId());
                if (entity == null) {
                    vo.setStatus(ResultStatus.FAILED);
                    vo.setErrorReason("合同用户不存在！");
                    return vo;
                }
            }
            //编辑计费规则
            contractUserService.editBillingRule(contractUserEntityVO);
            vo.setStatus(ResultStatus.SUCCESS);
            vo.getData().put("msg", "编辑计费规则成功！");
        } catch (Exception ex) {
            Log.error(ContractUserController.class, "编辑计费规则失败", ex);
            vo.setStatus(ResultStatus.FAILED);
            vo.setErrorReason("编辑计费规则失败！");
            LogUtil.errorLog(ContractUserController.class, ex, "editBillingRule()");
        }
        return vo;
    }

    private Map<String, Object> inputContractUserParams(Map<String, Object> map) throws
            PermissionVerifyException, ParamValidException {
        Map<String, Object> paramMap = Maps.newHashMap();
        try {
            //合同用户主键ID
            Integer contractUserId = map.get("contractUserId") == null || "".equals(map.get("contractUserId").toString()) ? null : Integer.valueOf(map.get("contractUserId").toString());
            //第几页
            Integer pageNum = map.get("pageNum") == null || "".equals(map.get("pageNum")) ? 1 : Integer.parseInt(map.get("pageNum").toString());
            //每页页数
            Integer pageSize = map.get("pageSize") == null || "".equals(map.get("pageSize")) ? PAGE_SIZE_DEFAULT : Integer.parseInt(map.get("pageSize").toString());

            paramMap.put("contractUserId", contractUserId);
            paramMap.put("pageNum", pageNum);
            paramMap.put("pageSize", pageSize);
        } catch (Exception e) {
            throw new ParamValidException("输入参数错误");
        }
        return paramMap;
    }
}